#ifndef __TOYM__BASE__BLOCKING_QUEUE_H__
#define __TOYM__BASE__BLOCKING_QUEUE_H__

#include <mutex>
#include <condition_variable>
#include <deque>
#include "Base/noncopyable.h"

namespace toym
{

template<typename T>
class BlockingQueue: noncopyable {
public:
    BlockingQueue();

    std::size_t size() const {
        return m_queue.size();
    }

    void push(const T& t) {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_queue.push_back(t);
        m_cond.notify_one();
    };
    void push(T&& t) {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_queue.push_back(std::move(t));
        m_cond.notify_one();
    }

    void pop() {
        std::unique_lock<std::mutex> lock(m_mutex);
        while (size() == 0) {
            m_cond.wait(lock);
        }
        m_queue.pop_front();
    }
    T& peek() {
        std::unique_lock<std::mutex> lock(m_mutex);
        while (size() == 0) {
            m_cond.wait(lock);
        }
        return m_queue.front();
    }
    T popAndGet() {
        std::unique_lock<std::mutex> lock(m_mutex);
        while (size() == 0) {
            m_cond.wait(lock);
        }
        T tmp = std::move(m_queue.front());
        m_queue.pop_front();
        return tmp;
    }

private:
    std::deque<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable m_cond;
};

} // namespace toym


#endif //__TOYM__BASE__BLOCKING_QUEUE_H__